#include "thread.hpp"
#include "unistd.h"
#include "lockguard.hpp"

using namespace threadModel;

// void print(const std::string &name)
// {
//     int cnt = 1;
//     while (true)
//     {
//         std::cout << name << "is running, cnt: " << cnt++ << std::endl;
//         sleep(1);
//     }
    
// }

// const int gnum = 10;

// int main()
// {
//     // 构建线程对象
//     std::vector<mythread> mythreads;
//     for (int i = 0; i < gnum; i++)
//     {
//         std::string name = "thread-" + std::to_string(i + 1);
//         mythreads.emplace_back(name, print);
//         sleep(1);
//     }

//     // 统一启动
//     for(auto &mythread : mythreads)
//     {
//         mythread.start();
//     }

//     sleep(10);
    
//     // 将所有进程统一结束
//     for(auto &mythread : mythreads)
//     {
//         mythread.stop();
//     }

//     // 主线程统一等待所有子线程
//     for(auto &mythread : mythreads)
//     {
//         mythread.join();
//     }



    // mythread t("thread_1", print);
    // t.start();
    // std::cout << t.name() << ", status: "<< t.status() << std::endl;

    // sleep(10);
    // std::cout << t.name() << ", status: "<< t.status() << std::endl;

    // t.stop();
    // sleep(1);
    // std::cout << t.name() << ", status: "<< t.status() << std::endl;

    // t.join();
    // std::cout << "join done" << std::endl;

    // return 0;
// }

// 多线程抢票程序

int tickets = 10000;

// pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;

void route(threadData *td)
{
    //以下两行是为了测试，通过设计threadData是不是能够达到不同线程访问同一把锁的目的
    // std::cout << td->_name << ": mutex address: " << td->_lock << std::endl;
    // sleep(1);
    while (true)
    {
        // 使用lockGuard这个类型的对象可以保证
        // 1. 每次在执行循环体中的代码块时，都会执行pthread_mutex_lock这个函数
        //    即在lockGuard对象调用构造函数后就会直接进行上锁操作，
        // 2. 每次在循环体执行完毕后，会销毁在代码块中申请的变量，
        //    此时就会调用lockGuard的析构函数，此时就会调用pthread_mutex_unlock这个函数
        //    即在每次程序执行出当前代码快都会解锁
        lockGuard lockguard(td->_lock);
        if (tickets > 0)
        {
            //抢票过程
            usleep(1000);
            printf("who: %s, get a ticket: %d\n", td->_name.c_str(), tickets);
            tickets--;
        }
        else
        {
            break;
        }
    }
}

// void route(threadData *td)
// {
//     //以下两行是为了测试，通过设计threadData是不是能够达到不同线程访问同一把锁的目的
//     // std::cout << td->_name << ": mutex address: " << td->_lock << std::endl;
//     // sleep(1);
//     while (true)
//     {
//         pthread_mutex_lock(td->_lock);
//         if (tickets > 0)
//         {
//             //抢票过程
//             usleep(1000);
//             printf("who: %s, get a ticket: %d\n", td->_name.c_str(), tickets);
//             tickets--;
//             pthread_mutex_unlock(td->_lock);
//         }
//         else
//         {
//             pthread_mutex_unlock(td->_lock);
//             break;
//         }
//     }
// }

static int threadnum = 4;

int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, nullptr);
    std::vector<mythread> threads;
    for (int i = 0; i < threadnum; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        threadData *td = new threadData(name, &mutex);        
        threads.emplace_back(name, route, td);
    }

    for(auto &thread : threads)
    {
        thread.start();
    }

    for(auto &thread : threads)
    {
        thread.join();
    }

    pthread_mutex_destroy(&mutex);
    
    // mythread t1("thread-1", route);
    // mythread t2("thread-2", route);
    // mythread t3("thread-3", route);
    // mythread t4("thread-4", route);
    // t1.start();
    // t2.start();
    // t3.start();
    // t4.start();

    // t1.join();
    // t2.join();
    // t3.join();
    // t4.join();
    return 0;
}